package cn.com.egova.erp.biz.impl;

import cn.com.egova.erp.biz.IEmpBiz;
import cn.com.egova.erp.dao.IEmpDao;
import cn.com.egova.erp.dao.IMenuDao;
import cn.com.egova.erp.dao.IRoleDao;
import cn.com.egova.erp.entity.Emp;
import cn.com.egova.erp.entity.Menu;
import cn.com.egova.erp.entity.Role;
import cn.com.egova.erp.entity.Tree;
import cn.com.egova.erp.exception.ErpException;
import com.alibaba.fastjson.JSON;
import org.apache.shiro.crypto.hash.Md5Hash;
import redis.clients.jedis.Jedis;

import java.util.ArrayList;
import java.util.List;

/**
 * 员工业务逻辑类
 *
 * @author Administrator
 */
public class EmpBiz extends BaseBiz<Emp> implements IEmpBiz {

    private int hashIterations = 2;

    private IEmpDao empDao;

    private IRoleDao roleDao;

    private IMenuDao menuDao;

    private Jedis jedis;

    public void setEmpDao(IEmpDao empDao) {
        this.empDao = empDao;
        super.setBaseDao(this.empDao);
    }

    public void setRoleDao(IRoleDao roleDao) {
        this.roleDao = roleDao;
    }

    public void setMenuDao(IMenuDao menuDao) {
        this.menuDao = menuDao;
    }

    public void setJedis(Jedis jedis) {
        this.jedis = jedis;
    }

    /**
     * 用户登陆
     *
     * @param username
     * @param pwd
     * @return
     */
    @Override
    public Emp findByUsernameAndPwd(String username, String pwd) {
        //查询前先加密
//        pwd = encrypt(pwd, username);
//        System.out.println(pwd);
        return empDao.findByUsernameAndPwd(username, pwd);
    }

    /**
     * 修改密码
     */
    @Override
    public void updatePwd(Long uuid, String oldPwd, String newPwd) {
        //取出员工信息
        Emp emp = empDao.get(uuid);
        //加密旧密码
        String encrypted = encrypt(oldPwd, emp.getUsername());
        //旧密码是否正确的匹配
        if (!encrypted.equals(emp.getPwd())) {
            //抛出 自定义异常
            throw new ErpException("旧密码不正确");
        }
        empDao.updatePwd(uuid, encrypt(newPwd, emp.getUsername()));
    }

    /**
     * 新增员工
     */
    @Override
    public void add(Emp emp) {
        //String pwd = emp.getPwd();
        // source: 原密码
        // salt:   盐 =》扰乱码
        // hashIterations: 散列次数，加密次数
        //Md5Hash md5 = new Md5Hash(pwd, emp.getUsername(), hashIterations);
        //取出加密后的密码
        //设置初始密码
        String newPwd = encrypt(emp.getUsername(), emp.getUsername());
        //System.out.println(newPwd);
        //设置成加密后的密码
        emp.setPwd(newPwd);
        //保存到数据库中
        super.add(emp);
    }

    /**
     * 重置密码
     */
    @Override
    public void updatePwd_reset(Long uuid, String newPwd) {
        //取出员工信息
        Emp emp = empDao.get(uuid);
        empDao.updatePwd(uuid, encrypt(newPwd, emp.getUsername()));
    }

    /**
     * 加密
     *
     * @param source
     * @param salt
     * @return
     */
    private String encrypt(String source, String salt) {
        Md5Hash md5 = new Md5Hash(source, salt, hashIterations);
        return md5.toString();
    }


    @Override
    public List<Tree> readEmpRoles(Long uuid) {
        List<Tree> treeList = new ArrayList<>();
        //获取用户信息
        Emp emp = empDao.get(uuid);
        //获取用户配置的角色信息
        List<Role> empRoles = emp == null ? new ArrayList<>() : emp.getRoles();
        //获取全部角色列表
        List<Role> roles = roleDao.getList(null, null, null);
        Tree t1 = null;
        for (Role role : roles) {
            t1 = new Tree();
            t1.setId(role.getUuid() + "");
            t1.setText(role.getName());
            if (empRoles.contains(role)) {
                t1.setChecked(true);
            }
            treeList.add(t1);
        }
        return treeList;
    }

    @Override
    public void updateEmpRoles(Long uuid, String checkedStr) {
        Emp emp = empDao.get(uuid);
        //先清空所有角色
        emp.setRoles(new ArrayList<>());
        //ids为前端传过来的roleuuid字符串
        String[] ids = checkedStr.split(",");
        Role role = null;
        for (String id : ids) {
            role = roleDao.get(Long.valueOf(id));
            emp.getRoles().add(role);
        }
        //用户角色改变时清除regis缓存，以便使用新的菜单权限
        jedis.del("menuList_" + uuid);
    }

    @Override
    public List<Menu> getMenusByEmpUuid(Long uuid) {
        List<Menu> menuList = null;
        //尝试从缓存取出menuList
        String menuListJson = jedis.get("menuList_" + uuid);
        if (menuListJson == null) {
            System.out.println("-----------getMenusByEmpUuid-----------------");
            System.out.println("-----get menuList from db-------------");
            menuList = empDao.getMenusByEmpUuid(uuid);
            System.out.println(menuList.toString());
            //redis里只可以存储字符串
            jedis.set("menuList_" + uuid, JSON.toJSONString(menuList));
        } else {
            System.out.println("------get menuList from cache--------------");
            menuList = JSON.parseArray(menuListJson, Menu.class);
        }
        return menuList;
    }

    /**
     * 获取用户菜单 树形结构
     *
     * @param uuid
     * @return
     */
    @Override
    public Menu readMenuByEmpuuid(Long uuid) {
        //获取所有菜单，做模板用.注意：Menu进行了自关联，get("0")得到整个菜单树
        Menu root = menuDao.get("0");
        //获取用户下的菜单集合(非树形结构)
        List<Menu> empMenus = empDao.getMenusByEmpUuid(uuid);
        //构建菜单树
        Menu _root = cloneMenu(root);
        //循环匹配模板
        Menu _m1 = null;
        Menu _m2 = null;
        //遍历一级菜单
        for (Menu m1 : root.getMenus()) {
            _m1 = cloneMenu(m1);
            //遍历二级菜单
            for (Menu m2 : m1.getMenus()) {
                //只有包含在用户菜单中的二级菜单才能添加进一级菜单
                if (empMenus.contains(m2)) {
                    _m2 = cloneMenu(m2);
                    _m1.getMenus().add(_m2);
                }
            }
            //只有当一级菜单下有子菜单时才添加进根菜单
            if (_m1.getMenus().size() > 0) {
                _root.getMenus().add(_m1);
            }
        }
        return _root;
    }

    /**
     * 克隆菜单
     * 注意：只克隆本级菜单，不管子菜单
     *
     * @param src
     * @return
     */
    private Menu cloneMenu(Menu src) {
        Menu menu = new Menu();
        menu.setMenuid(src.getMenuid());
        menu.setMenuname(src.getMenuname());
        menu.setIcon(src.getIcon());
        menu.setUrl(src.getUrl());
        //注意：只克隆本级菜单，不管子菜单
        menu.setMenus(new ArrayList<>());
        return menu;
    }
}
